<template>
  <div class="canvas-box" @mousedown="mousedown">
    <canvas></canvas>
    <div class="canvas-point" :style="pointStyle"></div>
  </div>
</template>

<script>
import {Color, HUES} from "../color";
import util from "../util";

export default {
  name: "PickerCanvas",
  props: {
    value:{type:String,default:"#000000"},
    color:{type:Color,default:new Color()}
  },
  data() {
    let data={
      pointX:0,
      pointY:0,
      rect:null,
      ctx2d:null,
      target:this.value,
      //color:new Color(this.value),
      feedback:true
    }
    return data;
  },
  mounted() {
    this.rect=util.getElementRect(this.$el);
    let canvas=this.$el.querySelector("canvas");
    setTimeout(()=>{
      canvas.width=this.rect.width;
      canvas.height=this.rect.height;
      this.ctx2d=canvas.getContext('2d');
      //console.log(HUES)
      this.fromChange();
    },10)
  },
  methods:{
    /**
     * 监听鼠标拖动,并计算点坐标
     * @param {MouseEvent} ev
     */
    mousedown(ev){
      let me=this;
      //console.log(ev)
      if(ev.button===0){
        document.documentElement.style.cursor="pointer";
        me.feedback=false;
        let rect=this.rect=util.getElementRect(this.$el);
        let computePoint=function (ev){
          let cPointX=rect.width-ev.clientX+rect.left;
          let cPointY=ev.clientY-rect.top;
          if(cPointX<=0) cPointX=0;
          if(cPointX>=rect.width) cPointX=rect.width;
          if(cPointY<0) cPointY=0;
          if(cPointY>=rect.height) cPointY=rect.height;

          me.pointX=cPointX;
          me.pointY=cPointY;
          //console.log(rect.width-cPointX,cPointY)

          me.doChange(cPointX,cPointY)
        };
        computePoint(ev)
        //console.log(util.toJSON(ev,"offsetX","offsetY","",""))
        let mouseMove=function (ev){
          if(ev.buttons===1){
            computePoint(ev)
          }else {
            document.documentElement.style.cursor=""
            me.feedback=true;
            window.removeEventListener("mousemove",mouseMove)
            window.removeEventListener("mouseup",mouseUp)
          }
          //console.log(ev);
        };
        let mouseUp=function (ev){
          document.documentElement.style.cursor="";
          me.feedback=true;
          window.removeEventListener("mousemove",mouseMove)
          window.removeEventListener("mouseup",mouseUp)
        }
        window.addEventListener("mousemove",mouseMove);
        window.addEventListener("mouseup",mouseUp);
      }
    },
    /**
     * 通过坐标改变颜色
     * @param cPointX
     * @param cPointY
     */
    doChange(cPointX,cPointY){
      let sRGB=HUES[this.color.h];
      let eRGB={r:255,g:255,b:255};
      let color=[sRGB.r,sRGB.g,sRGB.b]

      if(cPointX>0 && cPointX<this.rect.width) {
        color = this.ctx2d.getImageData(this.rect.width - cPointX, cPointY, 1, 1).data;
      }else{
        let sY=(1-cPointY/this.rect.height);
        let bColor=cPointX?eRGB:sRGB
        color[0]=Math.round(bColor.r*sY);
        color[1]=Math.round(bColor.g*sY);
        color[2]=Math.round(bColor.b*sY);
      }
      this.target=this.color.toHex();
      this.$emit("change",...color)
    },
    /**
     * 通过颜色更新坐标
     */
    fromChange(){
      let color=this.color;
        let sRGB=HUES[color.h];
        let sMax=sRGB.r>sRGB.g?'r':'g';
        sMax=sRGB[sMax]>sRGB.b?sMax:'b';
        let eMin=sRGB.r<sRGB.g?'r':'g';
        eMin=sRGB.b<sRGB[eMin]?'b':eMin;
        let sY=1-color[sMax]/255;
        let sX=color[eMin]/color[sMax];
        this.pointX=Math.round(this.rect.width*sX);
        this.pointY=Math.round(this.rect.height*sY);
        this.renderCanvas()
    },
    /**
     * 渲染canvas 渐变
     */
    renderCanvas() {
      //console.log(this.color.h)
      let hue = HUES[this.color.h];
      let ctx = this.ctx2d
      let width = ctx.canvas.width, height = ctx.canvas.height;

      let star = {r: 255, g: 255, b: 255};
      let end = hue
      for (let i = 0; i <= height; i++) {
        let grd = ctx.createLinearGradient(0, 0, width, 1);
        let bl = (height - i) / height;
        let r = Math.round(star.r * bl);
        let g = Math.round(star.g * bl);
        let b = Math.round(star.b * bl);
        grd.addColorStop(0, Color.rgb2hex(r, g, b));

        r = Math.round(end.r * bl);
        g = Math.round(end.g * bl);
        b = Math.round(end.b * bl);
        grd.addColorStop(1, Color.rgb2hex(r, g, b));

        ctx.fillStyle = grd;
        ctx.fillRect(0, i, width, 1);
      }
    },
  },
  watch:{
    'color.h'(n,o){
      if(this.feedback) {
        this.fromChange()
      }
    },
    'color.r'(n,o){
      if(this.feedback) {
        this.fromChange()
      }
    },
    'color.g'(n,o){
      if(this.feedback) {
        this.fromChange()
      }
    },
    'color.b'(n,o){
      if(this.feedback) {
        this.fromChange()
      }
    },
  },
  computed:{
    pointStyle(){
      let c=HUES[(this.color.h+180)%360];
      return {right:this.pointX-6+'px',
        top:this.pointY-6+'px',borderColor:`rgb(${c.r},${c.g},${c.b})`}
    },
  }
}
</script>

<style>
.canvas-box{
  position: relative;
  height: 125px;
  overflow: hidden;
}
.canvas-box * {
  box-sizing: border-box;
}
.canvas-box >canvas{
  display: block;
  width: 100%;
  height: 100%;
  background-color: white;
}
.canvas-point {
  position: absolute;
  width: 13px;
  height: 13px;
  border: 1px solid #ffffff;
  border-radius: 6px;
  right: 0px;
  top: 0px;
}
</style>
